package com.ron.android.daneel;

import java.util.Date;

import android.content.ContentProvider;
import android.content.ContentProviderDatabaseHelper;
import android.content.ContentURIParser;
import android.content.ContentValues;
import android.content.QueryBuilder;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.ContentURI;
import android.text.TextUtils;
import android.util.Log;

import com.ron.provider.Daneel;

public class DaneelProvider extends ContentProvider {

	private SQLiteDatabase db;

	private static final String APP_ID = "Daneel";
	private static final String DATABASE_NAME = "daneel.db";
	private static final int DATABASE_VERSION = 1;

	private static final int NOTES = 1;
	private static final int NOTE_ID = 2;
	private static final int TAGS = 3;
	private static final int TAG_ID = 4;

	private static final ContentURIParser URI_MATCHER;

	private static final class DatabaseHelper extends
			ContentProviderDatabaseHelper {

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("CREATE TABLE notes (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
							+ "text TEXT);");
			db.execSQL("CREATE TABLE tags (_id INTEGER PRIMARY KEY AUTOINCREMENT,"
							+ "note_id INTEGER, text TEXT);");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(APP_ID, "Upgrading database from version " + oldVersion
							+ " to " + newVersion
							+ ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS notes");
			db.execSQL("DROP TABLE IF EXISTS tags");
			onCreate(db);

		}

	}

	@Override
	public boolean onCreate() {
		DatabaseHelper dbHelper = new DatabaseHelper();
		db = dbHelper.openDatabase(getContext(), DATABASE_NAME, null,
				DATABASE_VERSION);
		return (db == null) ? false : true;
	}

	@Override
	public String getType(ContentURI uri) {

		String type = "";

		switch (URI_MATCHER.match(uri)) {
		case NOTES:
			type = "vnd.android.cursor.dir/vnd.ron.note";
			break;

		case NOTE_ID:
			type = "vnd.android.cursor.item/vnd.ron.note";
			break;

		case TAGS:
			type = "vnd.android.cursor.dir/vnd.ron.tag";
			break;

		case TAG_ID:
			type = "vnd.android.cursor.item/vnd.ron.tag";
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		return type;
	}

	@Override
	public int delete(ContentURI uri, String selection, String[] selectionArgs) {
		int count = db.delete(getTables(uri), "_id=" + uri.getPathLeafId(), null);
		if(count > 0){
			deleteAllTags( uri.getPathLeafId() );
			getContext().getContentResolver().notifyChange(uri, null);
		}
		return count;
	}

	private void deleteAllTags(long noteId) {
		db.delete("tags", "note_id =" + noteId, null);
	}

	@Override
	public ContentURI insert(ContentURI uri, ContentValues values) {
		
		ContentValues insertValues = values != null ? values : new ContentValues(); 
		
		if( URI_MATCHER.match(uri) != NOTES ){
			throw new IllegalArgumentException( "Unknown URI " + uri );
		}
		
		long rowId;
		rowId = db.insert(getTables(uri), "text", insertValues);
		
		if( rowId > 0 ){
			ContentURI notifyURI = Daneel.Notes.CONTENT_URI.addId(rowId);
			getContext().getContentResolver().notifyChange(uri, null);
			addInitialSystemTags( rowId );
			return notifyURI;
		}
		
		throw new SQLException("Insert into " + uri + " failed.");
	}

	private void addInitialSystemTags(long noteId) {
		String date = new Date().toString();
		addTag(noteId, "entry_date:" + date);
		addTag(noteId, "modified_date:" + date);
	}
	
	private void addTag( long noteId, String tagText ){
		ContentValues tagValues = new ContentValues();
		tagValues.put("note_id", noteId);
		tagValues.put("text", tagText);
		db.insert("tags", "text", tagValues);
	}

	@Override
	public Cursor query(ContentURI uri, String[] projection, String selection,
			String[] selectionArgs, String groupBy, String having,
			String sortOrder) {
		Cursor cursor = null;
		QueryBuilder qb = new QueryBuilder();

		qb.setTables(getTables(uri));

		int uriMatch = URI_MATCHER.match(uri);
		if ((uriMatch == NOTE_ID) || (uriMatch == TAG_ID)) {
			qb.appendWhere("_id=" + uri.getPathLeafId());
		}

		String orderBy = getOrderBy(sortOrder);

		cursor = qb.query(db, projection, selection, selectionArgs, groupBy,
				having, orderBy);

		return cursor;
	}

	@Override
	public int update(ContentURI uri, ContentValues values, String selection,
			String[] selectionArgs) {
		String table = getTables(uri);
		String whereClause = "_id=" + uri.getPathLeafId();
		int count = db.update(table, values, whereClause, null);
		if(count > 0){
			updateSystemTags( uri.getPathLeafId() );
			getContext().getContentResolver().notifyChange(uri, null);
		}
		return count;
	}
	
	private void updateSystemTags(long noteId) {
		updateTag(noteId, "modified_date:" + (new Date()).toString());
	}
	
	private void updateTag( long noteId, String tagText ){
		String systemTagName = tagText.substring(0, tagText.indexOf(":"));
		String whereClause = "note_id=" + String.valueOf(noteId) + 
			" and text like '" + systemTagName + "%'"; 
		db.delete("tags", whereClause, null);
		addTag( noteId, tagText );
	}

	private String getOrderBy(String sortOrder) {
		String orderBy = sortOrder;
		if (TextUtils.isEmpty(sortOrder)) {
			orderBy = Daneel.Notes.DEFAULT_SORT_ORDER;
		}
		return orderBy;
	}

	private String getTables(ContentURI uri) {
		String table = "";
		switch (URI_MATCHER.match(uri)) {
		case NOTES:
		case NOTE_ID:
			table = "notes";
			break;
		case TAGS:
		case TAG_ID:
			table = "tags";
		default:
			throw new IllegalArgumentException("Unknown URI: [" + uri + "]");
		}
		return table;
	}

	static {
		URI_MATCHER = new ContentURIParser(ContentURIParser.NO_MATCH);
		URI_MATCHER.addURI("com.ron.provider.Daneel", "notes", NOTES);
		URI_MATCHER.addURI("com.ron.provider.Daneel", "notes/#", NOTE_ID);
		URI_MATCHER.addURI("com.ron.provider.Daneel", "tags", TAGS);
		URI_MATCHER.addURI("com.ron.provider.Daneel", "tags/#", TAG_ID);
	}
}
